package com.luolc.instantmessager.contact;
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2016-2017 Luolc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import android.util.Log;

import com.hyphenate.easeui.domain.EaseUser;
import com.hyphenate.easeui.utils.EaseCommonUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import java8.util.stream.Collectors;
import java8.util.stream.StreamSupport;

public class ContactRepo {
  private static final String TAG = ContactRepo.class.getSimpleName();

  private static ContactRepo sInstance;

  private static final String BASE_URL =
      "https://gitee.com/LuoLiangchen/InstantMessager/raw/master/server/";

  private static final Map<String, EaseUser> DEFAULT_USER_MAPPER;

  private static final Set<String> DEFAULT_GROUP_IDS;

  private final Gson gson = new Gson();

  private final Map<String, EaseUser> userMapper;

  private final Set<String> groupIds;

  static {
    final List<EaseUser> users = new LinkedList<>();
    users.add(createUser("jirui", "冀锐", null));
    users.add(createUser("liuxulin", "刘旭林", null));
    users.add(createUser("jiliang", "吉梁", null));
    users.add(createUser("menghaohan", "孟浩瀚", null));
    users.add(createUser("pangxiao", "庞骁", null));
    users.add(createUser("zhangzixuan", "张子玄", null));
    users.add(createUser("zhujinshun", "朱金顺", null));
    users.add(createUser("liyin", "李银", null));
    users.add(createUser("yangdongou", "杨冬偶", null));
    users.add(createUser("liuxiaoxuan", "柳晓萱", null));
    users.add(createUser("wangning", "王宁", null));
    users.add(createUser("mengcong", "蒙聪", null));
    users.add(createUser("weiqinglang", "韦庆朗", null));
    users.add(createUser("luoliangchen", "骆梁宸", null));
    users.add(createUser("huangjie", "黄杰", null));
    users.add(createUser("qihouji", "齐厚基", null));
    users.add(createUser("huangzhou", "黄舟", null));
    DEFAULT_USER_MAPPER = StreamSupport.stream(users)
        .collect(Collectors.toMap(EaseUser::getUsername, u -> u));

    DEFAULT_GROUP_IDS = new LinkedHashSet<>();
    DEFAULT_GROUP_IDS.add("35756558057474");
  }

  private static EaseUser createUser(String id, String nickname, String avatar) {
    final EaseUser user = new EaseUser(id);
    user.setNickname(nickname);
    user.setAvatar(avatar);
    EaseCommonUtils.setUserInitialLetter(user);
    return user;
  }

  private ContactRepo() {
    userMapper = new LinkedHashMap<>(DEFAULT_USER_MAPPER);
    groupIds = new LinkedHashSet<>(DEFAULT_GROUP_IDS);
  }

  public static ContactRepo getInstance() {
    ContactRepo instance = sInstance;
    if (sInstance == null) {
      synchronized (ContactRepo.class) {
        if (sInstance == null) {
          instance = new ContactRepo();
          sInstance = instance;
        }
      }
    }
    return instance;
  }

  public void syncUsers() {
    final String url = BASE_URL + "users.json";
    try (InputStream response = new URL(url).openStream()) {
      try (InputStreamReader reader = new InputStreamReader(response)) {
        final List<User> users = gson.fromJson(reader, new TypeToken<List<User>>() {
        }.getType());
        userMapper.clear();
        final Map<String, EaseUser> toUpdate = StreamSupport.stream(users)
            .collect(Collectors.toMap(
                User::getUserId,
                user -> createUser(user.getUserId(), user.getNickname(), user.getAvatar())));
        userMapper.putAll(toUpdate);
        Log.d(TAG, "syncUsers success");
        Log.d(TAG, "user count: " + userMapper.size());
      }
    } catch (IOException ex) {
      // ignore
      ex.printStackTrace();
    }
  }

  public void syncGroups() {
    final String url = BASE_URL + "groups.json";
    try (InputStream response = new URL(url).openStream()) {
      try (InputStreamReader reader = new InputStreamReader(response)) {
        final List<Group> groups = gson.fromJson(reader, new TypeToken<List<Group>>() {
        }.getType());
        groupIds.clear();
        final Set<String> toUpdate = StreamSupport.stream(groups)
            .map(Group::getGroupId)
            .collect(Collectors.toSet());
        groupIds.addAll(toUpdate);
        Log.d(TAG, "syncUsers success");
        Log.d(TAG, "group count: " + groupIds.size());
      }
    } catch (IOException ex) {
      // ignore
      ex.printStackTrace();
    }
  }

  public Set<String> getUserContactIds() {
    return userMapper.keySet();
  }

  public Set<String> getGroupContactIds() {
    return new LinkedHashSet<>(groupIds);
  }

  public UserProfileProvider createUserProfileProvider() {
    return new UserProfileProvider(userMapper);
  }
}
